package com.itbaizhan.openhis.controller.system;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.itbaizhan.openhis.aspectj.Log;
import com.itbaizhan.openhis.aspectj.enums.BusinessType;
import com.itbaizhan.openhis.constants.Constants;
import com.itbaizhan.openhis.constants.HttpStatus;
import com.itbaizhan.openhis.domain.LoginInfo;
import com.itbaizhan.openhis.domain.Menu;
import com.itbaizhan.openhis.domain.SimpleUser;
import com.itbaizhan.openhis.dto.LoginBodyDto;
import com.itbaizhan.openhis.service.LoginInfoService;
import com.itbaizhan.openhis.service.MenuService;
import com.itbaizhan.openhis.utils.AddressUtils;
import com.itbaizhan.openhis.utils.IpUtils;
import com.itbaizhan.openhis.utils.ShiroSecurityUtils;
import com.itbaizhan.openhis.vo.ActiverUser;
import com.itbaizhan.openhis.vo.AjaxResult;
import com.itbaizhan.openhis.vo.MenuTreeVo;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 用户登录
 */
@RestController
@Slf4j
public class LoginController {
	
	@Autowired
	private MenuService menuService;
	
	@Autowired
	private LoginInfoService loginInfoService;
	
	/**
	 * 登录方法
	 *
	 * @return 结果
	 */
	@PostMapping("login/doLogin")
	@Log(title = "用户登录", businessType = BusinessType.INSERT)//添加日志切面
	public AjaxResult login(@RequestBody @Validated LoginBodyDto loginBodyDto, HttpServletRequest request){
		log.info("用户登录开始");
		AjaxResult ajaxResult = AjaxResult.success();
		
		String username = loginBodyDto.getUsername();//用户名
		String password = loginBodyDto.getPassword();//密码
		
		UsernamePasswordToken token = new UsernamePasswordToken(username, password);
		
		// 记录LoginInfo登录日志
		
		LoginInfo loginInfo  = createLoginInfo(request);
		loginInfo.setLoginAccount(loginBodyDto.getUsername());//登录账号
		
		Subject subject = SecurityUtils.getSubject();
		
		try {
			subject.login(token);
			Serializable webToken = subject.getSession().getId();
			ajaxResult.put(Constants.TOKEN, webToken);
			//登录成功，记录登录信息
			loginInfo.setMsg("登录成功");
			loginInfo.setLoginStatus(Constants.LOGIN_SUCCESS);
			loginInfo.setUserName(ShiroSecurityUtils.getCurrentSimpleUser().getUserName());
			
		} catch (AuthenticationException e) {
			log.error("用户登录失败");
			ajaxResult = AjaxResult.error(HttpStatus.ERROR, "用户名或密码错误");
			loginInfo.setMsg("用户名或密码错误");
			loginInfo.setLoginStatus(Constants.LOGIN_ERROR);
		}
		
		//保存登陆信息到数据库
		loginInfoService.insertLoginInfo(loginInfo);
		
		return ajaxResult;
	}
	
	/**
	 * 创建登录对象信息
	 * @param request
	 * @return
	 */
	private LoginInfo createLoginInfo(HttpServletRequest request) {
		LoginInfo loginInfo = new LoginInfo();
		//获取浏览器信息
		UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
		String ipAddr = IpUtils.getIpAddr(request);//ip
		String osName = userAgent.getOperatingSystem().getName();//操作系统
		String browserName = userAgent.getBrowser().getName();//浏览器类型
		String realAddressByIP = AddressUtils.getRealAddressByIP(ipAddr);//获取登录地址
		loginInfo.setIpAddr(ipAddr);
		loginInfo.setLoginLocation(realAddressByIP);
		loginInfo.setBrowser(browserName);
		loginInfo.setOs(osName);
		loginInfo.setLoginTime(DateUtil.date());//登录时间
		loginInfo.setLoginType(Constants.LOGIN_TYPE_SYSTEM);//系统用户登录
		return loginInfo;
	}
	
	/**
	 * 获取用户信息
	 * @return
	 */
	@GetMapping("login/getInfo")
	public AjaxResult getInfo(){
		log.info("获取用户信息开始");
		AjaxResult ajaxResult = AjaxResult.success();
		
		Subject subject = SecurityUtils.getSubject();
		ActiverUser activerUser = (ActiverUser)subject.getPrincipal();
		
		ajaxResult.put("username", activerUser.getUser().getUserName());//用户名
		ajaxResult.put("picture", activerUser.getUser().getPicture());//头像
		ajaxResult.put("roles", activerUser.getRoles());//角色
		ajaxResult.put("permissions", activerUser.getPermissions());//权限
		
		return ajaxResult;
	}
	
	/**
	 * 获取菜单信息
	 * @return
	 */
	@GetMapping("login/getMenus")
	public AjaxResult getMenus(){
		Subject subject = SecurityUtils.getSubject();
		ActiverUser activerUser = (ActiverUser)subject.getPrincipal();
		boolean isAdmin = activerUser.getUser().getUserType().equals(Constants.USER_ADMIN);
		List<Menu> menus = menuService.selectMenuTree(isAdmin);
		ArrayList<MenuTreeVo> menuVos = new ArrayList<>();
		for (Menu menu : menus) {
			menuVos.add(new MenuTreeVo(menu.getMenuId().toString(),menu.getPath(),true));
		}
		return AjaxResult.success(menuVos);
	}
	
	/**
	 * 退出方法
	 * @return
	 */
	@PostMapping("login/logout")
	public AjaxResult logout(){
		log.info("用户退出开始");
		Subject subject = SecurityUtils.getSubject();
		subject.logout();
		return AjaxResult.success("用户退出成功");
	}


}
